#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <icu.h>

#include "libs.h"

void init_list(struct file_link* head, size_t total_size)
{
	memset(head, 0, sizeof(struct file_link));
	head->chapter = -1;
	head->offset = total_size;
	INIT_LIST_HEAD(&head->list);
}


//attach to tail
void insert_list(struct file_link* head, char* name, size_t len,
	size_t offset)
{
	struct file_link* node;
	struct file_link* pre;
	size_t total;

	node = malloc(sizeof(struct file_link));
	if (!node)
		return;

	memcpy(node->chapter_name, name, len);
	node->chapter_name[len] = 0;
	node->offset = offset;
	node->len = 0;
	total = head->offset;

	list_add_tail(&node->list, &head->list);
	pre = (struct file_link*)list_prev_entry(node, struct file_link, list);
	//calc chapter length
	node->chapter = pre->chapter + 1;
	node->len = total - node->offset; //only valid for last node
	if (node->chapter == 1) {
		pre->len = node->offset; //chapter 0 offset saved total size
	} else {
		pre->len = node->offset - pre->offset;
	}
	
}


void destroy_list(struct file_link* head)
{
	struct file_link* cur;
	struct file_link* n;

	//struct list_head* pos;
	//list_for_each(pos, &head->list) {

	//list_for_each_entry(cur, &head->list, list, struct file_link) {
	list_for_each_entry_safe(cur, n, &head->list, list, struct file_link) {
		list_del(&cur->list);
		free(cur);
	}
}


/* single list with head node: end */

#ifdef WINDOWS
#include <Windows.h>
#include <lm.h>
//max convert 128 words
int u8_to_gb2312(char* in, int in_len, char* out, int* out_len)
{
	int len, ori_len;
	char mid[512];

	//ori_len = strlen(in);
	ori_len = in_len;
	//convert an MBCS string to widechar, in to mid
	len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)in, ori_len, NULL, 0);
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)in, ori_len, (LPWSTR)mid, len);
	//mid to out
	len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)mid, len, NULL, 0, NULL, NULL);
	WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)mid, -1, (LPSTR)out, len, NULL, NULL);
	*out_len = len;
	return 0;
}

//utf_content = to_utf(buf, size, &realsize);
//gb2312 to utf8, should free memory by caller
char* to_utf(char* in, int in_len,  int* out_len)
{
	char* mid;
	char* out;
	int len;

	//in to mid
	//Maps a character string to a UTF-16 (wide character) string
	len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)in, -1, NULL, 0);
	len = len * sizeof(wchar_t);
	mid = malloc(len);
	MultiByteToWideChar(CP_ACP, 0, (LPCSTR)in, -1, (LPWSTR)mid, len);

	//mid to out
	//Maps a UTF-16 (wide character) string to a new character string. 
	len = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)mid, -1, NULL, 0, NULL, NULL);
	out = malloc(len);
	WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)mid, -1, (LPSTR)out, len, NULL, NULL);

	free(mid);
	*out_len = len;
	return out;
}

/* if local is UTF-8, return 0
	else return 1(GB2312)
*/
unsigned int get_local_charset(void)
{
	//CPINFOEX info;
	//GetCPInfoEx (CP_ACP, 0, &info);
	if (GetACP() == 936) { //CP936 is GB2312
		return 1;
	}
	return 0;
}

#endif

void FWRITE_IGNORE(char* buf, int size, int count)
{
#ifdef WINDOWS
	char outbuf[512];
	int outlen;
	u8_to_gb2312(buf, count, outbuf, &outlen);
	fwrite(outbuf, size, outlen, stdout);
#else
	fwrite(buf, size, count, stdout);
#endif
	printf("\n");
}

void parse_title_name(char* path, char* title)
{
	char* head = path;
	char* last_head = path;

	strcpy(title, "novel");//default is novel
	while (head) {
		//find last \ or /
#ifdef WINDOWS
		head = strchr(head, '\\');
#else
		head = strchr(head, '/');
#endif
		if (head) {
			head++; //skip /
			last_head = head;
		}
	}

	head = strstr(last_head, ".txt");
	if (!head)
		return;
	*head = 0;
	strcpy(title, last_head);
	*head = '.';

	printf("path is %s\n", path);
	printf("novel name is %s\n", title);
}
	
//return 1 if utf8; otherwise return 0
int text_charset(char* buf, int size)
{
	UErrorCode status = U_ZERO_ERROR;
	UCharsetDetector* csd = ucsdet_open(&status);
	if (status)
		return 1;
	ucsdet_setText(csd, (const char*)buf, size, &status);
	if (status)
		return 1;
	int32_t matchCount;
	const UCharsetMatch** csm = ucsdet_detectAll(csd, &matchCount, &status);
	if (status)
		return 1;
	UErrorCode err = U_ZERO_ERROR;
	const char* name = ucsdet_getName(csm[0], &err);
	//const char* lang = ucsdet_getLanguage(csm[0], &err);
	//int32_t confidence = ucsdet_getConfidence(csm[0], &err);
	if(err != U_ZERO_ERROR)
		return 1;

	printf("txt file character set is %s\n", name);
	if (strcmp(name, "UTF-8"))
		return 0;
	
	return 1;
}